import asyncio
import random

import requests
from pyppeteer import launch
from cookiespool.libs import get_random_proxy, get_trajectory_1, get_sms_code
from cookiespool.config import TEST_URL_MAP

HIDE_WEBDRIVER = '''() => {Object.defineProperty(navigator, 'webdriver', {get: () => undefined})}'''
SET_USER_AGENT = '''() => {Object.defineProperty(navigator, 'userAgent', {get: () => '%s'})}'''
SET_APP_VERSION = '''() => {Object.defineProperty(navigator, 'appVersion', {get: () => '5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'})}'''
EXTEND_LANGUAGES = '''() => {Object.defineProperty(navigator, 'languages', {get: () => ['zh-CN', 'zh', 'en', 'zh-TW', 'ja']})}'''
EXTEND_PLUGINS = '''() => {Object.defineProperty(navigator, 'plugins', {get: () => [0, 1, 2, 3, 4]})}'''
EXTEND_MIME_TYPES = '''() => {Object.defineProperty(navigator, 'mimeTypes', {get: () => [0, 1, 2, 3, 4]})}'''
CHANGE_WEBGL = '''() => {
    const getParameter = WebGLRenderingContext.getParameter
    WebGLRenderingContext.prototype.getParameter = (parameter) => {gunicorn 
      if (parameter === 37445) {
        return 'Intel Open Source Technology Center'
      }
      if (parameter === 37446) {
        return 'Mesa DRI Intel(R) Ivybridge Mobile '
      }
      return getParameter(parameter)
    }
  }
'''
SET_CHROME_INFO = '''() => {
  Object.defineProperty(window, 'chrome', {
    "app": {
      "isInstalled": false,
      "InstallState": {"DISABLED": "disabled", "INSTALLED": "installed", "NOT_INSTALLED": "not_installed"},
      "RunningState": {"CANNOT_RUN": "cannot_run", "READY_TO_RUN": "ready_to_run", "RUNNING": "running"}
    },
    "runtime": {
      "OnInstalledReason": {
        "CHROME_UPDATE": "chrome_update",
        "INSTALL": "install",
        "SHARED_MODULE_UPDATE": "shared_module_update",
        "UPDATE": "update"
      },
      "OnRestartRequiredReason": {"APP_UPDATE": "app_update", "OS_UPDATE": "os_update", "PERIODIC": "periodic"},
      "PlatformArch": {
        "ARM": "arm",
        "ARM64": "arm64",
        "MIPS": "mips",
        "MIPS64": "mips64",
        "X86_32": "x86-32",
        "X86_64": "x86-64"
      },
      "PlatformNaclArch": {"ARM": "arm", "MIPS": "mips", "MIPS64": "mips64", "X86_32": "x86-32", "X86_64": "x86-64"},
      "PlatformOs": {
        "ANDROID": "android",
        "CROS": "cros",
        "LINUX": "linux",
        "MAC": "mac",
        "OPENBSD": "openbsd",
        "WIN": "win"
      },
      "RequestUpdateCheckStatus": {
        "NO_UPDATE": "no_update",
        "THROTTLED": "throttled",
        "UPDATE_AVAILABLE": "update_available"
      }
    }
  })
}
'''

CHANGE_PERMISSION = '''() => {
  const originalQuery = window.navigator.permissions.query;
  return window.navigator.permissions.query = (parameters) => (
    parameters.name === 'notifications' ?
      Promise.resolve({ state: Notification.permission }) :
      originalQuery(parameters)
  )
}
'''


async def get_douyin_cookie(username, password):
    result = {
        'status': 3
    }

    try:
        browser = await launch(headless=False, defaultViewport=None,
                               ignoreDefaultArgs=[
                                   '--enable-automation'
                               ],
                               args=['--disable-infobars',
                                     '--no-sandbox',
                                     '--blink-settings=imagesEnabled=false',
                                     '--disable-setuid-sandbox',
                                     '--password-store=basic',
                                     '--account-consistency',
                                     '--aggressive',
                                     # '--proxy-server={}'.format(get_random_proxy()),
                                     '--allow-running-insecure-content',
                                     '--allow-no-sandbox-job',
                                     '--allow-outdated-plugins',
                                     '--disable-gpu'])
        context = await browser.createIncognitoBrowserContext()
        page = await context.newPage()

        await page.evaluateOnNewDocument(HIDE_WEBDRIVER)
        await page.evaluateOnNewDocument(EXTEND_LANGUAGES)
        await page.evaluateOnNewDocument(EXTEND_PLUGINS)
        await page.evaluateOnNewDocument(EXTEND_MIME_TYPES)
        await page.evaluateOnNewDocument(CHANGE_WEBGL)
        await page.evaluateOnNewDocument(SET_CHROME_INFO)
        await page.evaluateOnNewDocument(CHANGE_PERMISSION)

        await page.goto('https://www.douyin.com/', {'waitUntil': 'networkidle2'})

        # 等待弹出登录框
        while not await page.querySelector('#login-pannel'):
            pass

        # 切换到密码输入
        change_login_btn = await page.querySelectorAll(".web-login-tab-list__item")
        await change_login_btn[2].click()
        await asyncio.sleep(3)

        # 输入手机号
        username_input = await page.querySelector(".web-login-normal-input__input")
        await username_input.type(username)
        await asyncio.sleep(2)

        # 获取验证码
        send_code_btn = await page.querySelector('.web-login-button-input__button-text')
        handle = await send_code_btn.boundingBox()
        handleX = handle.get('x') + handle.get('width') / 2
        handleY = handle.get('y') + handle.get('height') / 2
        trajectories = get_trajectory_1(handle.get('x'))

        for trajectory in trajectories[0]:
            print(trajectory[0] + handleX, trajectory[1] + handleY, trajectory[2])
            await page.mouse.move(trajectory[0] + handleX, trajectory[1] + handleY,
                                  options={'steps': random.randint(10, 30)})
        await send_code_btn.click()
        await asyncio.sleep(10)

        # 滑块
        captcha = await page.querySelector('#captcha_container')
        if captcha:
            await browser.close()

        code = get_sms_code(username)
        if not code:
            raise KeyError('sms code was not found')

        code_field = await page.querySelector('.web-login-button-input__input')
        await code_field.type(code)
        await asyncio.sleep(2)

        # 点击登录
        login_btn = await page.querySelector(".web-login-button")
        await login_btn.click()
        await asyncio.sleep(2)

        result['status'] = 1
        result['content'] = await page.cookies()

    finally:
        await browser.close()
        print('Successful to get cookies', result)
        return result


if __name__ == '__main__':
    asyncio.run(get_douyin_cookie('19901467533', 'test'))
